Skip to content

fix: adopt canonical hardened automerge template - #19

Merged
blytkerchan merged 1 commit into
masterfrom
fix/automerge-canonical-template
Aug 3, 2026
Merged

fix: adopt canonical hardened automerge template#19
blytkerchan merged 1 commit into
masterfrom
fix/automerge-canonical-template

Conversation

@blytkerchan

Copy link
Copy Markdown
Member

This repo is auto-merging unguarded right now

.github/workflows/ci_dependabot_automerge.yml calls gh pr merge --auto --squash with nothing gating it, and DEPENDABOT_AUTOMERGE_TOKEN is provisioned here — so this is live, not latent. Minor/patch Dependabot PRs are merging without waiting for ci_validate_jekyll.yml.

gh pr merge --auto does not mean "merge when CI passes"; it means "merge when the repository's merge requirements are satisfied". master has no branch protection and no required status check, so there are no requirements and it merges immediately. That is exactly how node-dashboard#37 merged past a failing plan job.

Fix

Verbatim copy of the canonical template from guidance@main. It polls the PR head commit's own check runs and blocks the merge unless every other check completed successfully — so it fails closed regardless of branch-protection config or plan tier.

ci_validate_jekyll.yml gives it something real to wait on.

Do not hand-edit it: the trigger, token handling, run-id self-exclusion and settle window are each load-bearing and each was a real failure elsewhere in the portfolio. See runbooks/dependabot-automerge.md.

Found during a cross-org scan on 2026-08-03 that extended to vln-bookstore, rxmail-io, vln-sneakyimmediatetapeworm and cpp4theselftaught — orgs not covered by earlier passes.

The workflow called gh pr merge --auto with nothing gating it, and this
repo has DEPENDABOT_AUTOMERGE_TOKEN provisioned, so minor/patch bumps
were auto-merging with nothing waiting on ci_validate_jekyll.yml.

Replaced with the canonical template from vln-devsecops/guidance, which
gates the merge on the PR head commit's own check runs.
Copilot AI review requested due to automatic review settings August 3, 2026 15:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens Dependabot auto-merge by replacing the existing workflow with a canonical template that gates merges on the PR head commit’s completed check runs, rather than relying on branch protection / required checks.

Changes:

  • Reworks the Dependabot auto-merge workflow to wait for (and validate) sibling check runs on the PR head SHA before approving/merging.
  • Makes auto-merge explicitly opt-in via DEPENDABOT_AUTOMERGE_TOKEN, with clear notice behavior when not provisioned.
  • Adds job-level safeguards and documentation comments for pull_request_target secret-handling and self-exclusion while polling checks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 15 to +18
permissions:
contents: write
pull-requests: write
checks: read

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, and fixed at the source: guidance#15 drops GITHUB_TOKEN to contents: read / pull-requests: read / checks: read.

Every write this workflow performs — the approve and the merge — goes through DEPENDABOT_AUTOMERGE_TOKEN, so the write scope bought nothing and, under pull_request_target, was pure blast radius: a compromised step or third-party action would have held a repo-write token. The suite now fails if any write scope is reintroduced.

This repo picks it up on the next resync from the canonical template.

Comment on lines +117 to +118
echo "No sibling check runs appeared within ${settle_seconds}s; nothing to gate on."
exit 0

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accurate, and the wording is mine to fix — the PR description overstates it.

The behaviour is deliberate: exiting 0 when no sibling checks appear is what lets a repo with no PR-triggered CI merge at all. But you are right that "fails closed" is then wrong as written, and the honest description is that it fails closed on any check it can see, and merges when it can see none.

Whether that should become a hard failure is a genuine open question now, because the standing rule changed: auto-merge is only supposed to be added once a repo has at least one check to gate on (guidance#14). Under that rule, a repo reaching this path is misconfigured, and failing closed would surface it rather than silently merging.

I have put it to the operator rather than changing it unilaterally — flipping it would stop merges in any repo that legitimately has no CI yet, across ~46 repos.

Comment on lines 22 to 23
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, and the sharpest point in the review — but I have deliberately not changed it, because it is a policy call rather than a pure bug fix. Raised with the operator.

The bug is real. github.actor is whoever triggered the event, not the PR author. On reopened, or when a maintainer pushes to the branch, github.actor is the human, the if evaluates false, and the job silently no-ops on a genuine Dependabot PR. Nothing reports that — it just never merges.

Why it is not a drive-by fix. Switching to github.event.pull_request.user.login also widens when auto-merge fires. Today, a human touching a Dependabot branch effectively opts that PR out of auto-merge. Keyed on the PR author, those PRs would auto-merge again — including any human-authored commits pushed onto the Dependabot branch, which is a plausible way for unreviewed changes to reach the default branch under an auto-merge label.

Both behaviours are defensible; they are different policies. Since the template is copied into ~46 repos, I would rather have that decided than pick silently. Tracked alongside guidance#15.

@blytkerchan
blytkerchan merged commit ac739e9 into master Aug 3, 2026
3 checks passed
@blytkerchan
blytkerchan deleted the fix/automerge-canonical-template branch August 3, 2026 15:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants